package co.recloud.ariadne.model.logical;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import co.recloud.ariadne.model.Host;
import co.recloud.ariadne.request.CommitGossipRequest;
import co.recloud.ariadne.request.TransactionRequest;
import co.recloud.ariadne.store.TransactionCache;
import co.recloud.ariadne.thread.Main;

public class Transaction implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = -4128389187020364142L;
	final public static int READY = 1;
	final public static int RUNNING = 2;
	final public static int PRECOMMIT = 3;
	final public static int COMMITTED = 4;
	final public static int ABORTED = 5;
	
	private Long id;
	private Long startTime;
	private Long commitTime;
	private int state;
	private Set<Host> hosts;
	
	public Transaction() {
		hosts = new HashSet<Host>();
	}
	/**
	 * @param id the id to set
	 */
	public void setId(Long id) {
		this.id = id;
	}
	/**
	 * @return the id
	 */
	public Long getId() {
		return id;
	}
	/**
	 * @param time the time to set
	 */
	public void setStartTime(Long time) {
		this.startTime = time;
	}
	/**
	 * @return the time
	 */
	public Long getStartTime() {
		return startTime;
	}
	/**
	 * @param state the state to set
	 */
	public void setState(int state) {
		this.state = state;
	}
	/**
	 * @return the state
	 */
	public int getState() {
		return state;
	}
	
	public String toString() {
		return "txn:{id: " + id + ", time: " + startTime + "}";
	}
	
	public void addHost(Host target) {
		hosts.add(target);
	}
	public Set<Host> getHosts() {
		return hosts;
	}
	public void generate() {
		setId((long) (Math.random() * (double) Long.MAX_VALUE));
		setStartTime(Main.getTime());
	}
	public void commit() {
		TransactionRequest txnRequest = new TransactionRequest();
		this.setState(COMMITTED);
		TransactionCache txnCache = TransactionCache.getInstance();
		txnCache.writeBack(this);
		txnCache.freeTransaction(this);
		txnRequest.setTransaction(this);
		txnRequest.sendBlocking();
		CommitGossipRequest commitReq = new CommitGossipRequest();
		commitReq.setTransaction(this);
		commitReq.gossip();
	}
	/**
	 * @param commitTime the commitTime to set
	 */
	public void setCommitTime(Long commitTime) {
		this.commitTime = commitTime;
	}
	/**
	 * @return the commitTime
	 */
	public Long getCommitTime() {
		return commitTime;
	}
}
